package Server;

import ClientFront.MainWindow;
import ClientFront.MyUtils;
import ClientFront.Net.MsgTypeEnum;
import ClientFront.NetMsg;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Stack;

public class Server {
    Socket socket;
    String clientName;
    String serverName = "不知名服务器";
    int userNum = 0;
    int turnNum = 1;
    public BlankTypeEnum nowPlayer = BlankTypeEnum.BLACK;
    public static Socket Player1;
    public static Socket Player2;
    public static boolean nextTrun = false;
    Thread P1th;
    Thread P2th;
    Stack<Integer> stepStack = new Stack<>();

    protected static ObjectOutputStream output1;
    protected static ObjectOutputStream output2;
    protected static ObjectInputStream input1;
    protected static ObjectInputStream input2;

    public void sendToOther(NetMsg msg, Socket whoAmI){//开摆
        if(whoAmI == Player1){
            sendToPlayer2(msg);
        }
        if(whoAmI == Player2){
            sendToPlayer1(msg);
        }
    }
    protected void sendToPlayer1(NetMsg msg){
        System.out.println("发送给玩家1："+msg.getMsgType());
        try{
            output1.writeUnshared(msg);
            output1.flush();
        }catch (Exception e){e.printStackTrace();
            System.out.println(msg.getMsgType().name());}
    }
    protected void sendToPlayer2(NetMsg msg){
        System.out.println("发送给玩家2："+msg.getMsgType());

        try{
            output2.writeUnshared(msg);
            output2.flush();

        }catch (Exception e){
            e.printStackTrace();
            System.out.println(msg.getMsgType().name());
        }
    }

    public int getTurnNum() {
        return turnNum;
    }
    public synchronized void  addTurnNum(){
        System.out.println("turn addded to"+turnNum+1);
        turnNum++;
    }

    public BlankTypeEnum[][] board = new BlankTypeEnum[ServerConsts.BOARD_LEN][ServerConsts.BOARD_LEN];

    Server(){
        init();
        try {
            ServerSocket serverSocket = new ServerSocket(9999);
            System.out.println("服务器启动,正在监听9999端口");
            while(userNum <= 2)
            {
                socket = serverSocket.accept();
                userNum++;
                NetMsg msg = new NetMsg(MsgTypeEnum.QUIT);
                if(userNum == 1){
                    input1 = new ObjectInputStream(socket.getInputStream());
                    msg =(NetMsg) input1.readUnshared();
                }
                if(userNum == 2){
                    input2 = new ObjectInputStream(socket.getInputStream());
                    msg =(NetMsg) input2.readUnshared();
                }

                if(msg.getMsgType() == MsgTypeEnum.LINKTEST){
                    clientName = msg.getArgs()[0];
                    System.out.println("连接成功！用户名为"+clientName);
                    if(userNum == 1){
                        output1 = new ObjectOutputStream(socket.getOutputStream());
                        output1.writeUnshared(new NetMsg(MsgTypeEnum.LINKACK,serverName));
                    }
                    if(userNum == 2)
                    {
                        output2 = new ObjectOutputStream(socket.getOutputStream());
                        output2.writeUnshared(new NetMsg(MsgTypeEnum.LINKACK,serverName));
                    }

                }
                if(userNum == 1){
                    Player1 = socket;
                    sendToPlayer1(new NetMsg(MsgTypeEnum.USEBLACK));
                    System.out.println("sended");
                    P1th = new Thread(new DealUserMsg(socket,BlankTypeEnum.BLACK).setTheServer(this));
                    P1th.start();
                }
                if(userNum == 2){
                    Player2 = socket;
                    sendToPlayer2(new NetMsg(MsgTypeEnum.USEWHITE));
                    sendToPlayer1(new NetMsg(MsgTypeEnum.GAMESTART));
                    sendToPlayer2(new NetMsg(MsgTypeEnum.GAMESTART));
                    nextTrun = true;
                    P2th = new Thread(new DealUserMsg(socket,BlankTypeEnum.WHITE).setTheServer(this));
                    P2th.start();
                }

            }
        }catch (Exception e){e.printStackTrace();}
    }

    void init(){
        clearBoard();
    }
    void clearBoard(){
        for (int i = 0; i < ServerConsts.BOARD_LEN; i++) {
            for (int j = 0; j < ServerConsts.BOARD_LEN; j++) {
                board[i][j] = BlankTypeEnum.BLANK;
            }
        }
    }
    BlankTypeEnum goStep(int step){
        int[] xy = MyUtils.stepToint(step);

        board[xy[0]][xy[1]] = nowPlayer;
        BlankTypeEnum winner = judgeWinner(xy[0],xy[1]);
        System.out.println("winner is" +winner.name());
        return winner;
    }
    synchronized BlankTypeEnum  judgeWinner(int x,int y){
        int starty;
        int endy;
        int startx;
        int endx;
        int cnt = 0;
        //u2d
        starty = Math.max(y - 4, 0);
        endy = Math.min(y + 5, ServerConsts.BOARD_LEN);
        for(;starty < endy;starty++)
        {
            if(board[x][starty] == nowPlayer){cnt++;}
            else{cnt = 0;}
            if(cnt >= ServerConsts.LESS_CNT_TO_WIN){return nowPlayer;}
        }

        //l2r
        cnt = 0;
        startx = Math.max(x - 4, 0);
        endx = Math.min(x + 5, ServerConsts.BOARD_LEN);
        for(;startx<endx;startx++){
            if(board[startx][y] == nowPlayer){cnt++;}
            else{cnt = 0;}
            if(cnt >= ServerConsts.LESS_CNT_TO_WIN){return nowPlayer;}
        }
        //lu2rd
        cnt = 0;
        int luNum = Math.min(x-Math.max(x-4,0),y-Math.max(y-4,0));
        int rdNum = Math.min(Math.min(x+5,ServerConsts.BOARD_LEN)-x,Math.min(y+5,ServerConsts.BOARD_LEN)-y);
        for(int startp = -luNum;startp < rdNum;startp++)
        {
            if(board[x+startp][y+startp] == nowPlayer){cnt++;}
            else {cnt=0;}
            if(cnt >=ServerConsts.LESS_CNT_TO_WIN){return nowPlayer;}
        }
        //ld2ru
        cnt = 0;
        int ldNum = Math.min(x-Math.max(x-4,0),Math.min(y+4,ServerConsts.BOARD_LEN-1)-y);
        int ruNum = Math.min(Math.min(x+5,ServerConsts.BOARD_LEN)-x,y-Math.max(y-5,-1));
        System.out.println("been here ldNum = "+ldNum+"ru= "+ruNum);
        for(int startp = -ldNum;startp < ruNum;startp++)
        {
            System.out.println("x="+(x+startp)+"y="+(y-startp));
            if(board[x+startp][y-startp] == nowPlayer){cnt++;}
            else {cnt=0;}
            if(cnt >=ServerConsts.LESS_CNT_TO_WIN){return nowPlayer;}
        }
        System.out.println("been here4");
        return BlankTypeEnum.BLANK;
    }
    void clearStack(){
        stepStack.clear();
    }
    void restartGame(){
        sendToPlayer2(new NetMsg(MsgTypeEnum.RESTART));
        sendToPlayer1(new NetMsg(MsgTypeEnum.RESTART));
        turnNum = 1;
        clearBoard();
        clearStack();
    }
    public synchronized void dealMsg(NetMsg msg,Socket WhoAmI){
        try {
            switch (msg.getMsgType()){
                case QUIT:
                    WhoAmI.close();
                    clearBoard();
                    sendToOther(new NetMsg(MsgTypeEnum.USERQUIT,"对方退出对局！"),WhoAmI);
                    break;
                case STEP:
                    nowPlayer =  turnNum % 2 == 1?BlankTypeEnum.BLACK:BlankTypeEnum.WHITE;
                    System.out.println("nowplayer:1:black 0:white"+turnNum%2);
                    switch (goStep(Integer.parseInt(msg.getArgs()[0]))){
                        case BLACK:
                            sendToPlayer1(new NetMsg(MsgTypeEnum.WIN));
                            sendToPlayer2(new NetMsg(MsgTypeEnum.LOSE));
                            restartGame();
                            return;
                        case WHITE:
                            sendToPlayer1(new NetMsg(MsgTypeEnum.LOSE));
                            sendToPlayer2(new NetMsg(MsgTypeEnum.WIN));
                            restartGame();
                            return;
                        case BLANK:
                            sendToOther(msg,WhoAmI);
                            break;
                    }

                    addTurnNum();
                    break;
            }
        }catch (Exception e){}

    }

    public static void main(String[] args) {
        new Server();
    }

}
